查看原文
其他

pyquery爬取豆瓣读书

2017-11-29

作者 大邓

用pyquery爬取豆瓣读书

正常来说,只要清楚些爬虫的任务需求,可以将写爬虫的逻辑顺序按照从大到小,或者从小到大。所以这篇文章可以倒着读或者正着读。本文按照从大到小逻辑编写代码和文章,如下图

本任务需求:

爬取豆瓣阅读所有书籍的书名、出版社、评分、简介等相关信息。


本文具体逻辑顺序:

  1. 先获取书籍类目及网址

  2. 获取每个类目所有页面的链接

  3. 获取书籍名、出版社、评分等信息

  4. 衔接前面4部分的代码。

本代码使用pyquery库对网页数据进行解析,如果对这方面不太熟悉,可阅读公众号之前的pyquery分享。另外我附两篇简书相关的pyquery知识分享,讲解的都是很常用的知识。

爬虫神器PyQuery的使用方法

《以 jQuery 之名 - 爬虫利器 PyQuery》 http://www.jianshu.com/p/b7436ae2889f?utmcampaign=hugo&utmmedium=readershare&utmcontent=note

《Python爬虫:PyQuery库的介绍与使用 》 http://www.jianshu.com/p/c07f7cd1b548?utmcampaign=hugo&utmmedium=readershare&utmcontent=note


一、获取豆瓣阅读所有类目及链接

https://book.douban.com/tag/


from pyquery import PyQuery as pq
import requests headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'}

#这里我还是使用requests库作为网络请求库,方便定制
resp = requests.get('https://book.douban.com/tag/', headers=headers)
tags_doc = pq(resp.text)

#获取豆瓣读书标签页的标签列表,此处返回的是PyQuery对象
tags_doc = pq(url='https://book.douban.com/tag/')

#查看https://book.douban.com/tag/的html数据信息
print(tags_doc.html())


#检验发现总共有6个大类(科技、经管、生活、文化、流行文学)
#print(len(tags_doc('.tagCol')))

""" 我们要获取大类下面的小类名(如文学中包含小说、外国文学、杂文等)及小类目的链接 """

for a in tags_doc('.tagCol').items('a'):    print(a)    
""" 与上面打印的a是相同的 for tag in tags_doc('.tagCol'):    for a in pq(tag).items('a'):        print(a) """

我们整理下上面的代码,写成一个专门获取小类目及链接的函数

def fetch_tags():    """    获取豆瓣阅读各个类名的标签名及链接    :return: 形如[(tag_name,link),(tag_name2,link2)...]的列表    """    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'}    # 获取豆瓣读书标签页的标签列表,此处返回的是PyQuery对象    resp = requests.get('https://book.douban.com/tag/',headers=headers)        tags_doc = pq(resp.text)    tagnames = []    # 获取class="tagCol"的table标签,提取table中的很多个a标签    for tag in tags_doc('.tagCol').items('a'):        #a标签中的href值        #link = 'https://book.douban.com'+tag.attr('href')        #a标签夹住的文本内容        tag_name = tag.text()        tagnames.append(tag_name)    return tagnames

二、获取某个标签的书籍信息

以“小说”类书籍为例,网址是这样的

#小说第一页网址
"https://book.douban.com/tag/小说?start=0&type=T"

#小说第二页网址
"https://book.douban.com/tag/小说?start=20&type=T"

。。。#小说第n页的网址  (n-1)*20
"https://book.douban.com/tag/小说?start={num}&type=T".format(num=(n-1)*20)

现在我们想知道某类标签所有的网址


url = 'https://book.douban.com/tag/{tag}?start={num}&type=T'

resp = requests.get(url.format(tag='小说',num=0))

p_doc = pq(resp.text)


""" class="paginator"的div节点 选取div中为a的直接子节点 从所有的a节点中选择最后一个a节点。 获取这个a节点的文本内容,即为总的页面数 """
pages = p_doc('.paginator').children('a').eq(-1).text()

#获取该标签所有的页面网址
purls = []

for page in range(pages):    purl = url.format(tag='小说',num=page*20)    purls.append(purl)

我们将上面的代码整理为一个函数

def tag_page_urls(tag='小说'):    """    获取某类标签所有的网址    :param tag: 书籍小类目名,如小说    :return: 返回该类目所有页面的网址    """    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'}    url = 'https://book.douban.com/tag/{tag}?start={num}&type=T'    resp = requests.get(url.format(tag=tag, num=0),headers=headers)    p_doc = pq(resp.text)        pages = p_doc('.paginator').children('a').eq(-1).text()    # 获取该标签所有的页面网址    purls = []    for page in range(int(pages)):        purl = url.format(tag=tag, num=page * 20)        purls.append(purl)    return purls

三、获取每个页面中书籍的信息

获取书籍具体信息,以小说类第一页例子,想办法获取该页所有的书籍信息。以此类推,换个网址,其他的页面的书籍信息也可以获取。


purl = 'https://book.douban.com/tag/小说?start=0&type=T'

resp = requests.get(purl,headers=headers)

p_doc = pq(resp.text)

for book in p_doc.items('.info'):    #print(type(book))  #<class 'pyquery.pyquery.PyQuery'>        #找class=”info“的div    #div的直接子节点    #从子节点中找a标签    #获取a标签的title属性值    title = book.children('h2').find('a').attr('title')    
   #出版社   获取class=”info“的div的class=”pub“的子节点的文本内容    public = book.children('.pub').text()    #评论数    comments = book.find('.pl').text()    #书籍简介  获取class=”info“的div倒数第二个子节点的文本    description = book.children().eq(-2).text()    print(title,public,comments,description)

整理上面的代码,封装为函数

def books_detail(purl,writer):    """    获取某页面所有的书籍信息    :param purl: 豆瓣阅读某类标签的某一页面的网址    :param writer: 这是从get_all_books_data函数中生成的writer,用来存储数据    :return: 返回该页面所有书籍的信息    """    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'}    resp = requests.get(purl,headers=headers)    p_doc = pq(resp.text)    for book in p_doc.items('.info'):        #print(type(book))  #<class 'pyquery.pyquery.PyQuery'>        title = book.children('h2').find('a').attr('title')        #出版社        public = book.children('.pub').text()        # 评分        rating = book.find('.rating_nums').text()        #评论数        comments = book.find('.pl').text()        #书籍简介        description = book.children().eq(-2).text()                detail = (title,public,rating,comments,description)        writer.writerow(detail)        print(detail)

四、豆瓣阅读爬虫

获取豆瓣所有书籍信息

def get_all_books_data(filename):    """    开始愉快的爬数据    :param filename: 保存数据的csv文件的文件名    :return:    """    import csv,time    file = '{}.csv'.format(filename)    with open(file,'a+',encoding='utf-8',newline='') as csvf:        writer = csv.writer(csvf)        writer.writerow(('书籍名','出版社','评论数','简述'))        for tag in fetch_tags():            for purl in tag_page_urls(tag=tag):                print(purl)                books_detail(purl=purl,writer=writer)                time.sleep(1)          get_all_books_data(filename='data')


历史文章:

数据采集

selenium驱动器配置详解

icrawler:强大简单的图片爬虫库

抓取单博主的所有微博及其评论

爬虫神器PyQuery的使用方法

pyquery一些自定义的用法

【视频】猫途鹰网站评论数据抓取

【视频讲解】在scrapy框架中如何使用selenium?

【实战视频】使用scrapy写爬虫-爬知乎live

简易SQLite3数据库学习

【视频教程】对视频进行基本操作

【视频】抓包小练习-B站评论数据抓取

fake-useragent库:值得花2分钟学习的库

【视频】爬取饿了么平台上的门店信息

如何抓取视频资源-以头条视频为例

当爬虫遭遇验证码,怎么办

【视频】手把手教你抓美女~

【视频】有了selenium,小白也可以自豪的说:“去TMD的抓包、cookie”

【视频】快来get新技能--抓包+cookie,爬微博不再是梦

【视频教程】用python批量抓取简书用户信息

识别假货有绝招,就用python爬淘宝评论

用Python抓取百度地图里的店名,地址和联系方式

文本处理分析

gensim:用Word2Vec进行文本分析

RAKE:快速自动抽取关键词算法

对于中文,nltk能做哪些事情

用nltk计算词语间的点互信息值PMI

Python NLP中的五大英雄

用SenticNet库做细粒度情感分析

如何对csv文件中的文本数据进行分析处理

复杂网络分析数据准备篇

文本分析之网络关系

用词云图解读“于欢案”

基于共现发现人物关系的python实现

用pyecharts制作词云图

图片数据处理

OpenCV:快速入门图片人脸识别

好玩的OpenCV:图片操作的基本知识(1)

好玩的OpenCV:图像操作的基本知识(2)

OpenCV:计算图片有多色

如何对数据进行各种排序?

其他

迅雷不给力,我DIY了个下载器

【视频】初学者必看:python环境配置

开扒皮自己微信的秘密

初识装饰器函数

计算运行时间-装饰器实现

花十分钟,给爱机安装个MongoDB

chardet库:轻松识别文件的编码格式

使用Python登录QQ邮箱发送QQ邮件

WTF Python: 开启你的懵逼模式

8行代码实现微信聊天机器人

WTF Python: 开启你的懵逼模式

WTF Python:开启懵逼模式第二弹

使用Python+OpenCV进行面部合成

十分钟学会用Flask发邮件


十分钟入门常用的json库


优雅简洁的列表推导式

【资源帖】简单易懂的机器学习视频教程



    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存